package com.dcits.components.threadpools;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Metrics;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.MetricsEndpoint;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.*;

@RestController
@RequestMapping("/monitor/metrics")
public class ActuatorMonitor {
    private final Map<String, MetricEntity> metricGroup = Maps.newHashMap();
    private final MeterRegistry meterRegistry;
    private final MetricsEndpoint metricsEndpoint;

    @Data
    public static class MetricEntity {
        private String name;
        private List<Object> data = new ArrayList<>();
        private String description;
        private List<String> tags = new ArrayList<>();
    }

    public ActuatorMonitor(MeterRegistry meterRegistry, MetricsEndpoint metricsEndpoint) {
        this.meterRegistry = meterRegistry;
        this.metricsEndpoint = metricsEndpoint;
    }

    @PostConstruct
    public void init() {
        metricGroup.put("application", new MetricEntity());
        metricGroup.put("disk", new MetricEntity());
        metricGroup.put("executor", new MetricEntity());
        metricGroup.put("jvm.buffer", new MetricEntity());
        metricGroup.put("jvm.classes", new MetricEntity());
        metricGroup.put("jvm.gc", new MetricEntity());
        metricGroup.put("jvm.memory", new MetricEntity());
        metricGroup.put("logback", new MetricEntity());
        metricGroup.put("process", new MetricEntity());
        metricGroup.put("system", new MetricEntity());
        metricGroup.put("threadpool", new MetricEntity());
        metricGroup.put("tomcat", new MetricEntity());
    }

    @GetMapping("list")
    public String list() {
        Map<String, Meter> metricMap = Maps.newHashMap();
        meterRegistry.forEachMeter(row -> {
            final Meter.Id id = row.getId();
            metricMap.put(id.getName(), row);
        });
        metricGroup.forEach((name, metric) -> {
            metricMap.forEach((metricName, row) -> {
                if (metricName.startsWith(name)) {
                    metric.setName(metricName);
                    metric.setDescription(row.getId().getDescription());
                    row.getId().getTags().forEach(tag -> {
                        metric.getTags().add(tag.getValue());
                        List<String> tags = new ArrayList<>();
                        final MetricsEndpoint.MetricResponse metric1 = metricsEndpoint.metric(metricName, tags);
                        metric.getData().add(metric1.getMeasurements());
                    });
                }
            });
        });
        return JSON.toJSONString(metricGroup);
    }
}
